package com.solace.thumbnailator.utils;

import cn.hutool.core.img.Img;
import cn.hutool.core.img.ImgUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import net.coobird.thumbnailator.Thumbnails;
import net.coobird.thumbnailator.geometry.Coordinate;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.image.ImageObserver;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Future;
import java.util.stream.Collectors;


/**
 * 作者 CG
 * 时间 2021/1/9 15:13
 * 注释 图片处理工具类
 */
@Slf4j
public class ImgUtils {
    public static void main(String[] args) throws IOException {
        String srcPath = "C:/Users/Cancer/Desktop/1.png";
        String inPath = "C:/Users/Cancer/Desktop/2.jpg";
        String outPath = "C:/Users/Cancer/Desktop/6.png";
        Img result;
        Img from = Img.from(new File(inPath));
//        Img from = Img.from(new URL("https://wemewtest.oss-cn-qingdao.aliyuncs.com/2018-08-20-15/153475199044634521.jpg"));
        //头像切圆
       /* Img round = circular(from);
        result = antiAliasing(round);
        result = circularSynthetic(Img.from(new File(srcPath)), new Point(210, 208), 102, result);*/
        //arc - 圆角弧度，0~1，为长宽占比
//        result = from.round(1D).scale(0.5F);
        //批量添加文字
        /*DrawFont ni = new DrawFont("迪迦奥特曼", new Font("宋体", Font.BOLD, 24), Color.blue, new Point(364, 199),DrawFont.FONT_NEWLINE,200,24);
        DrawFont hello = new DrawFont("四川省成都市高新区天府五街建信人寿199号", new Font("宋体", Font.BOLD, 30), Color.red, new Point(227, 1380),DrawFont.FONT_NEWLINE,500);
        result= drawFonts(result, Arrays.asList(ni, hello));*/
        /*BufferedImage read = ImageIO.read(new File(inPath));
        DrawFont drawFont = new DrawFont(new Point(172, 373), read, 892, 747);
        result = rectangular(Img.from(new File(srcPath)), Arrays.asList(drawFont));
        result.write(new File(outPath));*/
        DrawFont font = new DrawFont("迪迦奥特曼", new Font("宋体", Font.BOLD, 24), Color.blue, new Point(364, 199), DrawFont.FONT_NEWLINE, 200, 24);
        DrawFont hello = new DrawFont("四川省成都市高新区天府五街建信人寿199号", new Font("宋体", Font.BOLD, 30), Color.red, new Point(227, 1380), DrawFont.FONT_NEWLINE, 500);
        DrawFont logo = new DrawFont(new Point(210, 208), Img.from(new File(inPath)), 102);
        DrawFont logo2 = new DrawFont(new Point(962, 1706), Img.from(new File("C:/Users/Cancer/Desktop/11.jpg")), 151);
        DrawFont drawFont = new DrawFont(new Point(172, 373), Img.from(new File(inPath)), 892, 747,0.01D);
        result = conformity(Img.from(new File(srcPath)), font, drawFont, hello,logo,logo2);
        result.write(new File(outPath));
    }

    /**
     * 作者 CG
     * 时间 2021/1/12 9:53
     * 注释 整合方法
     */
    @SneakyThrows
    public static Img conformity(Img source, DrawFont... drawFonts) {
        long star = System.currentTimeMillis();
        List<DrawFont> logo = Arrays.stream(drawFonts).filter(x -> x.getType() == DrawFont.TYPE_LOGO).collect(Collectors.toList());
        Future<List<DrawFont>> submit = ThreadPoolUtil.submit(() -> {
            List<DrawFont> logoFuture = new ArrayList<>();
            for (DrawFont drawFont : logo) {
                Img img = drawFont.getImg();
                //图片切圆
                Img circular = circular(img);
                //图片平滑边缘
                Img aliasing = antiAliasing(circular);
                //写入处理的图形
                drawFont.setImg(aliasing);
                logoFuture.add(drawFont);
            }
            return logoFuture;
        });
        List<DrawFont> font = Arrays.stream(drawFonts).filter(x -> x.getType() == DrawFont.TYPE_FONT).collect(Collectors.toList());
        List<DrawFont> img = Arrays.stream(drawFonts).filter(x -> x.getType() == DrawFont.TYPE_IMG).collect(Collectors.toList());
        BufferedImage bufferedImage = ImgUtil.toBufferedImage(source.getImg());
        Graphics2D graphics = bufferedImage.createGraphics();
        //处理文字
        drawFonts(graphics, font);
        //处理图片
        source = rectangular(source, img);
        //处理头像
        List<DrawFont> drawLogo = submit.get();
        boolean done = submit.isDone();
        log.info("异步生成头像线程是否结束[{}]", done);
        if (!done){
            submit.cancel(true);
        }
        source = circularSynthetic(source, drawLogo);
        long end = System.currentTimeMillis();
        log.info("执行完成[{}]个任务,共耗时[{}]毫秒", drawFonts.length, (end - star));
        return source;
    }

    /**
     * 作者 CG
     * 时间 2021/1/10 10:43
     * 注释 头像图片合成
     *
     * @param source 背景图片
     *               point  背景图片圆中心点坐标
     *               radius 背景图片圆半径(像素)
     *               data   资源图片
     * @return
     */
    public static Img circularSynthetic(Img source, List<DrawFont> list) {
        BufferedImage bufferedImage = ImgUtil.toBufferedImage(source.getImg());
        if (list != null && !list.isEmpty()) {
            Thumbnails.Builder<BufferedImage> of = Thumbnails.of(bufferedImage);
            for (DrawFont drawFont : list) {
                Point point = drawFont.getPoint();
                Img data = drawFont.getImg();
                int radius = drawFont.getRadius();
                int x = point.x;
                int y = point.y;
                //计算合成图片大小
                int width = data.getImg().getWidth((ImageObserver) null);
                BigDecimal radiusBig = new BigDecimal(radius);
                BigDecimal widthBig = new BigDecimal(width / 2);
                BigDecimal multiple = radiusBig.divide(widthBig, 6, BigDecimal.ROUND_HALF_UP);
                Img scale = data.scale(multiple.floatValue());
                //计算坐标
                x = x - radius;
                y = y - radius;
                of.watermark(new Coordinate(x, y), ImgUtil.toBufferedImage(scale.getImg()), 1F);
            }
            try {
                bufferedImage = of.scale(1D).asBufferedImage();
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            return source;
        }
        return Img.from(bufferedImage);
    }

    /**
     * 作者 CG
     * 时间 2021/1/9 16:47
     * 注释 处理头像锯齿
     * 切圆以后的文件
     * scale 缩放比列
     */
    public static Img antiAliasing(Img img) {
        BufferedImage bufferedImage = ImgUtil.toBufferedImage(img.getImg());
        int width = bufferedImage.getWidth();
        Graphics2D graphics = bufferedImage.createGraphics();
//            BufferedImage newAvatar = new BufferedImage(width, width, BufferedImage.TYPE_4BYTE_ABGR);
        //透明底的图片====>开始位置头像边框
        {
//                Graphics2D graphics = newAvatar.createGraphics();
            //新创建一个graphics，这样画的圆不会有锯齿
            graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            int border = 2;
            //画笔是4.5个像素，BasicStroke的使用可以查看下面的参考文档
            //使画笔时基本会像外延伸一定像素，具体可以自己使用的时候测试
            graphics.setStroke(new BasicStroke(4.5F, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
            graphics.setColor(Color.WHITE);
            graphics.drawOval(border, border, width - border * 2, width - border * 2);
            graphics.dispose();
        }
        //====>绘制头像边框结束
        //合并图层
           /* newAvatar = Thumbnails.of(bufferedImage)
                    //绘制头像到新图层
                    .watermark(Positions.CENTER, ImgUtil.toBufferedImage(img.getImg()), 1F)
                    //绘制头像边框
                    .watermark(Positions.CENTER, newAvatar, 1F)
                    .scale(1D).asBufferedImage();*/
        return Img.from(bufferedImage);
    }

    /**
     * 作者 CG
     * 时间 2021/1/9 15:13
     * 注释 头像切圆
     * 拾取图片的长宽,取最小值
     * 从中心点-最小值/2为半径开始裁剪
     */
    public static Img circular(Img img) {
        int radius;
        int width = img.getImg().getWidth((ImageObserver) null);
        int height = img.getImg().getHeight((ImageObserver) null);
        radius = (width > height ? height : width) / 2;
        //裁剪图片
        return img.cut(0, 0, radius);
    }

    /**
     * 作者 CG
     * 时间 2021/1/11 16:58
     * 注释 批量绘制文字
     */
    public static void drawFonts(Graphics2D graphics, List<DrawFont> fonts) {
        if (fonts != null && !fonts.isEmpty()) {
            graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
            for (DrawFont index : fonts) {
                Point point = index.getPoint();
                String text = index.getText();
                Color color = index.getColor();
                Font font = index.getFont();
                int widthLength = index.getWidthLength();
                int x = point.x;
                int y = point.y;
                int fontMode = index.getFontMode();
                if (fontMode == DrawFont.FON_TOMIT) {
                    drawString(graphics, index);
                } else if (fontMode == DrawFont.FONT_NEWLINE) {
                    drawString(graphics, text, color, font, x, y, widthLength, index.getHeight());
                } else {
                    drawString(graphics, text, color, font, x, y);
                }
            }
            graphics.dispose();
        }
    }

    /**
     * 作者 CG
     * 时间 2021/1/11 19:17
     * 注释 不处理直接绘制
     */
    public static void drawString(Graphics2D graphics, String text, Color color, Font fonts, int x, int y) {
        graphics.setColor(color);
        graphics.setFont(fonts);
        graphics.drawString(text, x, y);
    }

    /**
     * 作者 CG
     * 时间 2021/1/11 19:17
     * 注释 超长省略
     */
    public static void drawString(Graphics2D graphics, DrawFont fonts) {
        String text = fonts.getText();
        Font font = fonts.getFont();
        Color color = fonts.getColor();
        Point point = fonts.getPoint();
        int x = point.x;
        int y = point.y;
        FontMetrics fg = graphics.getFontMetrics(font);
        //长度限制
        int widthLength = fonts.getWidthLength();
        //绘制字体长度(像素)
        int stringWidth = fg.stringWidth(text);
        if (stringWidth > widthLength) {
            //如果绘制字体长度超过预订长度
            int length = text.length();
            int strIndex = (widthLength * length) / stringWidth;
            text = text.substring(0, strIndex) + "...";
        }
        drawString(graphics, text, color, font, x, y);
    }

    /**
     * 作者 CG
     * 时间 2021/1/11 19:56
     * 注释 超长换行绘制
     */
    public static void drawString(Graphics2D graphics, String text, Color color, Font font, int x, int y, int widthLength, int spacing) {
        FontMetrics fg = graphics.getFontMetrics(font);
        //绘制字体长度(像素)
        int stringWidth = fg.stringWidth(text);
        //获取文字高度
        int height = fg.getHeight();
        if (stringWidth > widthLength) {
            //如果绘制字体长度超过预订长度
            int length = text.length();
            //获取一行字数
            int strIndex = (widthLength * length) / stringWidth;
            //截取一行文字
            String var1 = text.substring(0, strIndex);
            //绘制文字
            drawString(graphics, var1, color, font, x, y);
            //计算下行文字坐标
            y = y + height;
            //如果行距不为0,则调整位置
            if (spacing != 0) {
                y = y + spacing;
            }
            //截取剩余文字
            String var2 = text.substring(strIndex, length);
            //递归绘制
            drawString(graphics, var2, color, font, x, y, widthLength, spacing);
        } else {
            //如果没有超长直接绘制
            drawString(graphics, text, color, font, x, y);
        }
    }

    /**
     * 作者 CG
     * 时间 2021/1/11 20:39
     * 注释 图片合成
     */
    public static Img rectangular(Img img, List<DrawFont> list) {
        if (list != null && !list.isEmpty()) {
            Thumbnails.Builder<BufferedImage> of = Thumbnails.of(ImgUtil.toBufferedImage(img.getImg()));
            BufferedImage bufferedImage = null;
            try {
                BufferedImage temp;
                for (DrawFont drawFont : list) {
                    double round = drawFont.getRound();
                    Img fontImg = drawFont.getImg();
                    if (round>0&&round<=1){
                        fontImg = fontImg.round(round);
                    }
                    BufferedImage drawFontImage = ImgUtil.toBufferedImage(fontImg.getImg());
                    Point point = drawFont.getPoint();
                    temp = Thumbnails.of(drawFontImage).size(drawFont.getW(), drawFont.getH())
                            //此参数图片会被拉伸
                            .keepAspectRatio(false)
                            .asBufferedImage();
                    of = of.watermark(new Coordinate(point.x, point.y), temp, 1F);
                }
                bufferedImage = of.scale(1F).asBufferedImage();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return Img.from(bufferedImage);
        } else {
            return img;
        }
    }
}
